package com.eascs.web.sso.dubbo;

import java.util.Arrays;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.eascs.app.log.Logger;
import com.eascs.app.log.LoggerFactory;
import com.eascs.app.log.TraceLogger;
import com.eascs.common.util.ApplicationContextUtil;
import com.eascs.common.util.StringUtil;
import com.eascs.site.session.SessionData;
import com.eascs.site.session.SessionProvider;
import com.eascs.web.sso.SsoUser;
import com.eascs.web.sso.SsoUserInterceptor;
import com.eascs.web.sso.User;
import com.eascs.web.sso.UserHolder;

@Activate(group = Constants.PROVIDER, order = -10000 + 100)
public class SessionProviderFilter implements Filter {
	private final Logger logger = LoggerFactory.getLogger(SessionProviderFilter.class);

	private SessionProvider sessionProvider;
	private boolean sessionProviderInit = false;

	public SessionProviderFilter() {
		super();
	}

	@Override
	public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
		long start = System.currentTimeMillis();
		try {
			handle(invoker, invocation);
			Result result = invoker.invoke(invocation);
			UserHolder.clear();
			return result;
		} finally {
			long elapsed = System.currentTimeMillis() - start;
			long timeout = invoker.getUrl().getMethodParameter(invocation.getMethodName(), "timeout", Integer.MAX_VALUE);
			logger.debug("dubbo provider invoke end thread:{}, elapsed:{}ms ", Thread.currentThread().getId(), elapsed);
			if (invoker.getUrl() != null && (elapsed > timeout || (timeout == Integer.MAX_VALUE && TraceLogger.isTimeOut(elapsed, null)))) {
				logger.warn("dubbo provider invoke time out. method: {} arguments: {} , url is {}, invoke elapsed {} ms.", invocation.getMethodName(), Arrays.toString(invocation.getArguments()), invoker.getUrl(), elapsed);
			}
			TraceLogger.get().cleanup(false);
		}

	}

	private void handle(Invoker<?> invoker, Invocation invocation) {

		if (!sessionProviderInit) {
			sessionProvider = ApplicationContextUtil.getBean(SessionProvider.class);
			sessionProviderInit = true;
		}
		if (sessionProvider == null)
			return;

		String sessionId = invocation.getAttachment(SessionConsumerFilter.REQUEST_SESSION_ID);
		if (StringUtil.isBlank(sessionId))
			return;
		UserHolder.setUser(getUserFromSession(sessionId));
	}

	public User getUserFromSession(String sessionId) {
		logger.debug("get dubbo Attachments requestSessionId={}", sessionId);
		SessionData sessionData = sessionProvider.loadSessionData(sessionId, null);
		if (null == sessionData)
			return null;
		SsoUser user = (SsoUser) sessionData.get(SsoUserInterceptor.SESSIONSPEC_SSOUSER.getName());
		if (null == user)
			return null;
		return user.getUser();
	}

}
